package net.pws.common.persistence.spring;

import javax.sql.DataSource;

import net.pws.common.persistence.DataSourceAware;
import net.pws.common.persistence.EntityManager;
import net.pws.common.persistence.EntityManagerAware;
import net.pws.common.persistence.FinderFactory;
import net.pws.common.persistence.FinderFactoryAware;
import net.pws.common.persistence.QueryStatementManager;
import net.pws.common.persistence.QueryStatementManagerAware;
import net.pws.common.persistence.SessionFactoryAware;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.Assert;


public class PersistenceAutowireConfigurer implements
                                          BeanPostProcessor,
                                          InitializingBean {
    
    private static final Log logger = LogFactory.getLog(PersistenceAutowireConfigurer.class);
    
    private EntityManager entityManager;
    
    private DataSource dataSource;
    
    private SessionFactory sessionFactory;
    
    private FinderFactory finderFactory;
    
    private QueryStatementManager queryStatementManager;
    
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
    
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    
    public void setFinderFactory(FinderFactory finderFactory) {
        this.finderFactory = finderFactory;
    }
    
    public void setQueryStatementManager(QueryStatementManager queryStatementManager) {
        this.queryStatementManager = queryStatementManager;
    }
    
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        
        if (bean instanceof DataSourceAware && ((DataSourceAware) bean).getDataSource() == null) {
            ((DataSourceAware) bean).setDataSource(dataSource);
            if (logger.isDebugEnabled()) {
                logger.debug("Set DataSource of bean[ " + bean
                             + "] to "
                             + dataSource);
            }
        }
        
        if (bean instanceof SessionFactoryAware && ((SessionFactoryAware) bean).getSessionFactory() == null) {
            ((SessionFactoryAware) bean).setSessionFactory(sessionFactory);
            if (logger.isDebugEnabled()) {
                logger.debug("Set SessionFactory of bean[ " + bean
                             + "] to "
                             + sessionFactory);
            }
        }
        
        if (bean instanceof EntityManagerAware && ((EntityManagerAware) bean).getEntityManager() == null) {
            ((EntityManagerAware) bean).setEntityManager(entityManager);
            if (logger.isDebugEnabled()) {
                logger.debug("Set EntityManager of bean[ " + bean
                             + "] to "
                             + entityManager);
            }
        }
        
        if (bean instanceof FinderFactoryAware && ((FinderFactoryAware) bean).getFinderFactory() == null) {
            ((FinderFactoryAware) bean).setFinderFactory(finderFactory);
            if (logger.isDebugEnabled()) {
                logger.debug("Set FinderFactory of bean[ " + bean
                             + "] to "
                             + finderFactory);
            }
        }
        
        if (bean instanceof QueryStatementManagerAware && ((QueryStatementManagerAware) bean).getQueryStatementManager() == null) {
            ((QueryStatementManagerAware) bean).setQueryStatementManager(queryStatementManager);
            if (logger.isDebugEnabled()) {
                logger.debug("Set QueryStatementManager of bean[ " + bean
                             + "] to "
                             + queryStatementManager);
            }
        }
        
        return bean;
    }
    
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(entityManager);
        Assert.notNull(dataSource);
        Assert.notNull(sessionFactory);
        Assert.notNull(finderFactory);
    }
    
}
